/*
* Copyright 2013 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.apps.dashclock;
import com.google.android.apps.dashclock.api.DashClockExtension;
import com.google.android.apps.dashclock.render.WidgetRenderer;
import android.app.Service;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.text.TextUtils;
import static com.google.android.apps.dashclock.LogUtils.LOGD;
/**
* The primary service for DashClock. This service is in charge of updating widget UI (see {@link
* #ACTION_UPDATE_WIDGETS}) and updating extension data via an internal instance of {@link
* ExtensionHost} (see {@link #ACTION_UPDATE_EXTENSIONS}).
*/
public class DashClockService extends Service implements ExtensionManager.OnChangeListener {
private static final String TAG = LogUtils.makeLogTag(DashClockService.class);
/**
* Intent action for updating widget views. If {@link #EXTRA_APPWIDGET_ID} is provided, updates
* only that widget. Otherwise, updates all widgets.
*/
public static final String ACTION_UPDATE_WIDGETS =
"com.google.android.apps.dashclock.action.UPDATE_WIDGETS";
public static final String EXTRA_APPWIDGET_ID =
"com.google.android.apps.dashclock.extra.APPWIDGET_ID";
/**
* Intent action for telling extensions to update their data. If {@link #EXTRA_COMPONENT_NAME}
* is provided, updates only that extension. Otherwise, updates all active extensions. Also
* optional is {@link #EXTRA_UPDATE_REASON} (see {@link DashClockExtension} for update reasons).
*/
public static final String ACTION_UPDATE_EXTENSIONS =
"com.google.android.apps.dashclock.action.UPDATE_EXTENSIONS";
public static final String EXTRA_COMPONENT_NAME =
"com.google.android.apps.dashclock.extra.COMPONENT_NAME";
public static final String EXTRA_UPDATE_REASON =
"com.google.android.apps.dashclock.extra.UPDATE_REASON";
private ExtensionManager mExtensionManager;
private ExtensionHost mExtensionHost;
private Handler mUpdateHandler = new Handler();
@Override
public void onCreate() {
super.onCreate();
mExtensionManager = ExtensionManager.getInstance(this);
mExtensionManager.addOnChangeListener(this);
mExtensionHost = new ExtensionHost(this);
}
@Override
public void onDestroy() {
super.onDestroy();
mUpdateHandler.removeCallbacksAndMessages(null);
mExtensionManager.removeOnChangeListener(this);
mExtensionHost.destroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null) {
String action = intent.getAction();
if (ACTION_UPDATE_WIDGETS.equals(action)) {
handleUpdateWidgets(intent);
} else if (ACTION_UPDATE_EXTENSIONS.equals(action)) {
handleUpdateExtensions(intent);
}
}
return START_STICKY;
}
@Override
public void onExtensionsChanged() {
mUpdateHandler.removeCallbacks(mUpdateAllWidgetsRunnable);
mUpdateHandler.postDelayed(mUpdateAllWidgetsRunnable,
ExtensionHost.UPDATE_COLLAPSE_TIME_MILLIS);
}
private Runnable mUpdateAllWidgetsRunnable = new Runnable() {
@Override
public void run() {
handleUpdateWidgets(new Intent());
}
};
/**
* Updates a widget's UI.
*/
private void handleUpdateWidgets(Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
// Either update all app widgets, or only those which were requested.
int appWidgetIds[];
if (intent.hasExtra(EXTRA_APPWIDGET_ID)) {
appWidgetIds = new int[]{intent.getIntExtra(EXTRA_APPWIDGET_ID, -1)};
} else {
appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(
this, WidgetProvider.class));
}
StringBuilder sb = new StringBuilder();
for (int appWidgetId : appWidgetIds) {
sb.append(appWidgetId).append(" ");
}
LOGD(TAG, "Rendering widgets with appWidgetId(s): " + sb);
WidgetRenderer.renderWidgets(this, appWidgetIds);
}
/**
* Asks extensions to provide data updates.
*/
private void handleUpdateExtensions(Intent intent) {
int reason = intent.getIntExtra(EXTRA_UPDATE_REASON,
DashClockExtension.UPDATE_REASON_UNKNOWN);
// Either update all extensions, or only the requested one.
String updateExtension = intent.getStringExtra(EXTRA_COMPONENT_NAME);
if (!TextUtils.isEmpty(updateExtension)) {
ComponentName cn = ComponentName.unflattenFromString(updateExtension);
mExtensionHost.execute(cn, ExtensionHost.UPDATE_OPERATIONS.get(reason),
ExtensionHost.UPDATE_COLLAPSE_TIME_MILLIS, reason);
} else {
for (ComponentName cn : mExtensionManager.getActiveExtensionNames()) {
mExtensionHost.execute(cn, ExtensionHost.UPDATE_OPERATIONS.get(reason),
ExtensionHost.UPDATE_COLLAPSE_TIME_MILLIS, reason);
}
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}